package com.zh.mp.demo.aspect;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Aspect
@Component
public class TransactionAop {

    private DataSourceTransactionManager txManager;  // 在某一个类的开始进行注入

    private TransactionStatus status;

    @Autowired
    public TransactionAop(JdbcTemplate jdbcTemplate){
        this.txManager = new DataSourceTransactionManager(jdbcTemplate.getDataSource());
    }

    @Pointcut("execution(* com.zh.mp.demo.modules.demo.controller.UserController.save(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void beginTransaction() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 事物隔离级别，开启新事务
        this.status = txManager.getTransaction(def); // 获得事务状态

        System.out.println("before beginTransaction");
    }

    @After("pointcut()")
    public void commit() {
        System.out.println("after commit");
        if(!status.isCompleted()) {
            txManager.commit(status);
        }
    }

    @AfterReturning(value = "pointcut()", returning = "obj")
    public void afterReturning(Object obj) {
        System.out.println("afterReturning :: " + obj);
    }

    @AfterThrowing(value = "pointcut()", throwing="ex")
    public void afterThrowing(Throwable ex){
        System.out.println("afterThrowing  rollback " + ex.toString());
        if(!status.isCompleted()) {
            txManager.rollback(status);
        }
    }

//    @Around("pointcut()")
//    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//        try {
//            System.out.println("around");
//            return joinPoint.proceed();
//        } catch (Throwable e) {
//            e.printStackTrace();
//            throw e;
//        } finally {
//            System.out.println("around");
//        }
//    }
}
